[dbt] custom schemaを使って普段とは別のスキーマ下にデータモデルを作成する
大阪オフィスの玉井です。
今回は下記の機能を使ってみたので、ご紹介します。
dbtはどこにデータモデルを作るのか?
dbtはELTの「T」を担当するツールということで、分析に最適化されたテーブルやビューを簡単に構築することができる…というのは、dbtを調べたり触ったりしたことがある方はわかると思います。
では、その「分析に最適化されたテーブルやビュー」というのは、どのDB・どのスキーマに作られるのでしょうか。
ざっくりいうと最初の設定で指定した場所に作られる
DBについては、Projectを作成するときに、対象のDWHの接続情報を設定しますが、そのときに指定した場所になります。ついでに、スキーマも合わせて設定できますが、こちらは接続情報として設定するのではなく、ユーザー毎に持つ「開発用の資格情報」として設定します。
「なんでこの設定こんな分かれ方してんの?」って思っちゃいますが、「どのスキーマに作るか?」をユーザー毎に設定することによって、1つのDB下に開発ユーザーの分だけ開発用スキーマを用意することができます。これにより、開発者は自分専用のスキーマ下に(他との干渉を気にせず)データモデルを実際に構築することができます。普通のシステム開発でいうローカル環境みたいなものを、DWH上に用意するイメージですね(いわゆるビッグデータを扱う場合、ローカル環境オンリーでは到底検証できないため、開発中のDWHが使用できるメリットは大きいです)。
基本、Project内で指定できるスキーマは1つ
(1ユーザーにとっての)開発環境・及び本番環境において、各データモデルを作成するときに指定できるスキーマは、基本的に1つです。10個のデータモデルを作成したとして、そのデータモデルは全て(設定した)1つのスキーマ下に作成されます。
「それじゃ困る。このデータモデルは別のスキーマに格納したい」。そんなときに使うと助かるかもしれないのが、今回取り上げるcustom schemaになります。
やってみた
環境
- dbt Cloud
- 実行する時のJobのバージョンは0.19.1
- Snowflake 5.31.4
custom schemaを使わない場合
dbt側でこういう感じにモデルを作っているとします。
これを実行すると、DWH側ではこうなります。
フォルダ分けとか関係なく、DBT_SANDBOX
というスキーマ下にずら〜っと作られます。
custom schemaを使ってみる
今回は「tpch_2
というフォルダ下にあるモデルだけ別スキーマにしたい」をやってみます。
モデル毎に(構築先のスキーマを)指定する方法もありますが、今回はdbt_project.yml
でまとめて指定します。
下記のように、models
の部分で、+schema
で構築先のスキーマを指定することができます。ちなみに、事前に作っておく必要はありません(dbt側が作ってくれます)。
models: tpch_project: tpch: materialized: table tpch_2: +schema: another_schema
この状態で実行すると、下記のようにスキーマが別途作成されます。
custom schemaで作成されたスキーマの名前について
上記の画像を見て「あれ?」と思った方もいるのではないでしょうか。スキーマの名前がDBT_SANDBOX_ANOTHER_SCHEMA
となっていますね。YAMLファイルで記述したのはanother_schema
なのに。
これはdbtの仕様によるものです。dbtのcustom schemaは「元々設定してたスキーマ名」+「custom schemaで指定した名前」という命名規則になっています。
上記のようになっている理由はドキュメント(当記事冒頭参照)に書いてありますが、ここでもざっくり説明します。もし、こういう仕様ではなかった場合(記述した名前がそのまま使われた場合)…
- (前述したように)ユーザー毎にスキーマを持つ方法が想定されているため、開発ユーザーの数だけ、同名スキーマが乱立してしまう
- 本番環境にも開発と同名のスキーマができてしまう
上記のようなリスクを避けるため、dbtのcustom schemaは、なるべく同名を出さないようになっています。
命名ロジックを任意のものに変える
とはいえ、色々な事情があって、命名ロジックをカスタマイズしたいときもあると思います。大丈夫です。可能です。
実は、custom schemaの命名ロジックはマクロで書かれています(中身も公式ドキュメントにあります)。このマクロをユーザー側で作ったもので上書きすると、そちらのロジックが使用されます。
上書きといっても、手順は非常に簡単で、Macroフォルダ下にget_custom_schema.sql
を作れば、dbtはcustom schemaを実行する時、命名ロジックの参照先をこちらに切り替えます。
試しに、命名の順序を入れ替えたものを設定してみます。
{% macro generate_schema_name(custom_schema_name, node) -%} {%- set default_schema = target.schema -%} {%- if custom_schema_name is none -%} {{ default_schema }} {%- else -%} {{ custom_schema_name | trim }}_{{ default_schema }} {%- endif -%} {%- endmacro %}
この状態でdbtを実行すると、スキーマ名が変わりました。ロジックが入れ替わっていますね。
おわりに
ドキュメントによれば、中間テーブルのようなものはステージングスキーマに隠しておき、完成版だけ本来のスキーマに格納する、といった使い方もできるようです。
ただ、あまりにも大量で複雑なスキーマ構成にはできない(というか非常に大変)ので、なるべくdbtの仕様に合わせるような構成を予め検討しておいた方が、後々幸せになるかと思います。